Skip to content

Surface MHCflurry's antigen-processing (cleavage) score (#235) - #240

Merged
iskandr merged 2 commits into
masterfrom
mhcflurry-processing
Jul 9, 2026
Merged

Surface MHCflurry's antigen-processing (cleavage) score (#235)#240
iskandr merged 2 commits into
masterfrom
mhcflurry-processing

Conversation

@iskandr

@iskandr iskandr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Closes #235.

MHCflurry's Class1PresentationPredictor.predict() already returns a processing_score column (its antigen-processing / cleavage head) right next to presentation_score — and the MHCflurry wrapper read presentation_score/presentation_percentile while discarding processing_score. We were computing the processing prediction on every run and throwing it away.

Change

Emit it as a Kind.antigen_processing prediction. It depends only on the peptide + flanks, not the allele (verified: SIINFEKL0.96719 for both HLA-A*02:01 and HLA-B*07:02), so it's emitted once per peptide, allele-less, carrying the n_flank/c_flank context.

from mhctools import MHCflurry, Kind

r = MHCflurry(alleles=["HLA-A*02:01", "HLA-B*07:02"]).predict(
    ["SIINFEKL"], n_flanks=["AAA"], c_flanks=["KKK"])[0]

r.processing            # -> Prediction(SIINFEKL | antigen_processing | score=0.9672 | mhcflurry)
r.processing.score      # 0.96719  (== MHCflurry's raw processing_score)
r.processing.allele     # ""  (allele-independent)
  • No new dependency and no extra cost — the score was already computed.
  • getattr(row, "processing_score", None) guards older/newer mhcflurry builds without the column (no-op if absent).
  • kind_support() advertises antigen_processing as mhc_dependence/mhc_class = "none", matching the other allele-free processing predictors.

Small companions

  • PeptideResult.processing accessor for Kind.antigen_processing. The existing ProcessingPredictor already emits this kind, but there was a cleavage accessor for proteasome_cleavage and none for antigen_processing — filled the gap.
  • predict-table processing field token(antigen_processing, score), so the Add predict-table command to annotate CSVs with predictor scores (#231) #234 command can pin the processing kind: --predictor mhcflurry:proc:processing (avoids the kind-agnostic score ambiguity when a predictor emits several kinds).

Tests

  • test_mhcflurry_processing_score: asserts the emitted score matches MHCflurry's raw processing_score, is allele-less, carries the flanks, and that kind_support() advertises it as allele-independent.
  • Updated test_mhcflurry_multiple_alleles for the extra prediction (2 affinity + 1 presentation + 1 processing).
  • test_processing_field_token_pins_antigen_processing_kind in the (binary-free) annotate-table suite.

Compatibility

Additive by design. The new-API predict(), predict_dataframe(), and protein-scanning gain one extra antigen_processing prediction/row per peptide for MHCflurry (filterable by kind). The legacy predict_peptides and the CLI --output-csv path is untouched — it stays affinity-only, one BindingPrediction per (peptide, allele) — so existing long-format consumers see no change. Both are covered by regression tests (test_mhcflurry_legacy_predict_peptides_unchanged, test_mhcflurry_processing_score_without_flanks).

Version 3.21.0 → 3.22.0.

https://claude.ai/code/session_01LZahFhBSCiehXTESCYQ7wG

iskandr added 2 commits July 9, 2026 14:42
…#235)

MHCflurry's Class1PresentationPredictor.predict() already returns a
processing_score column (its antigen-processing / cleavage head) alongside
presentation_score, and the wrapper's predict() read the latter while dropping
the former. We were paying for the processing prediction on every run and
never emitting it.

Now emit it as a Kind.antigen_processing prediction. It depends only on the
peptide + flanks (not the allele), so it's identical across a peptide's
per-allele presentation rows -> emit one allele-less prediction per peptide,
carrying the n_flank/c_flank context. Uses getattr(row, "processing_score",
None) so older/newer mhcflurry builds without the column are a no-op.
kind_support() advertises antigen_processing as mhc_dependence/mhc_class
"none". No new dependency, no cost: the score was already computed.

Also:
  * pred.py: add a PeptideResult.processing accessor for Kind.antigen_processing
    (the ProcessingPredictor already emits this kind; there was a `cleavage`
    accessor for proteasome_cleavage but none for antigen_processing).
  * annotate.py: add a `processing` output-field token -> (antigen_processing,
    score) so `predict-table` can pin the processing kind, e.g.
    `--predictor mhcflurry:proc:processing`.

Tests: new test_mhcflurry_processing_score checks the emitted score matches
MHCflurry's raw processing_score, is allele-less, and carries flanks; updates
the multi-allele test for the extra prediction; adds an annotate-table test
for the `processing` field token. Version 3.21.0 -> 3.22.0.

Claude-Session: https://claude.ai/code/session_01LZahFhBSCiehXTESCYQ7wG
Two test gaps from the #240 review:
  * processing score is still emitted when no flanks are supplied (n_flank/
    c_flank empty), not only in the flanked path;
  * the legacy predict_peptides / CLI (--output-csv) path stays affinity-only
    (one BindingPrediction per peptide/allele, no antigen_processing), so
    existing long-format consumers are unaffected by the new predict() output.

Claude-Session: https://claude.ai/code/session_01LZahFhBSCiehXTESCYQ7wG
@iskandr
iskandr merged commit 3489942 into master Jul 9, 2026
5 checks passed
@iskandr
iskandr deleted the mhcflurry-processing branch July 9, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Surface MHCflurry's antigen-processing (cleavage) score instead of discarding it

1 participant